package com.szu.smart_illustrator.service;


import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.github.yulichang.query.MPJLambdaQueryWrapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.szu.smart_illustrator.common.R;
import com.szu.smart_illustrator.dto.param.picture.*;
import com.szu.smart_illustrator.dto.result.picture.GetPictureTypesResultDto;
import com.szu.smart_illustrator.entity.Picture;
import com.szu.smart_illustrator.entity.Picturecollected;
import com.szu.smart_illustrator.entity.Type;
import com.szu.smart_illustrator.entity.User;
import com.szu.smart_illustrator.mapper.PictureMapper;
import com.szu.smart_illustrator.mapper.PicturecollectedMapper;
import com.szu.smart_illustrator.mapper.PicturetypeMapper;
import com.szu.smart_illustrator.mapper.TypeMapper;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
public class PictureService {
    @Autowired
    PictureMapper pictureMapper;

    @Autowired
    TypeMapper typeMapper;
    @Autowired
    PicturetypeMapper picturetypeMapper;

    @Autowired
    PicturecollectedMapper picturecollectedMapper;

    @Value("${imagePath}")
    String imagePath;

    public static final String address = "http://172.29.41.43:3392/";

    public  static HashMap<Long,String> cMap = new HashMap<>();

    @PostMapping("GeneratePictureWithPicture")
    public R<Picture> generatePictureWithPicture(@ModelAttribute GeneratePictureWithPictureParamDto dto) throws IOException, InterruptedException {


        Long id = System.currentTimeMillis();
        cMap.put(id,"");
        String fileName = dto.getFile().getOriginalFilename();
        String p1 = fileName.substring(0,fileName.lastIndexOf('.'));
        String p2 = fileName.substring(fileName.lastIndexOf('.'));
        fileName = p1+System.currentTimeMillis()+p2;
       String filePath =    "D:\\image\\"+fileName;
        dto.getFile().transferTo(new File(filePath));
//        调用python服务
        HttpRequest.post("http://localhost:5000/do").body(JSONObject.toJSON(GetPictureParamDto.builder()
                .src(filePath)
                .id(id)
                .steps(dto.getStep())
                        .prompt(dto.getPrompt())
                .strength(dto.getStrength())
                .noise(dto.getNoise())
                .width(dto.getWidth())
                .height(dto.getHeight())
                .build()).toString()).contentType("application/json").execute();
        for (int i = 0; i < 220; i++) {
            if(cMap.get(id)!=""){
                Picture picture = Picture.builder()
                        .step(dto.getStep())
                        .strength(dto.getStrength())
                        .prompt(dto.getPrompt())
                        .noise(dto.getNoise())
                        .url(cMap.get(id))
                        .creatorId(dto.getUserId())
                        .width(dto.getWidth())
                        .height(dto.getHeight())
                        .build();
                    pictureMapper.insert(picture);
                return  R.success(picture);
            }
            Thread.sleep(1000);
        }

        return R.error("生成失败");
    }

    public R<List<Picture>> searchSharedPicture( SearchSharedPictureParamDto dto){
      String field = "name";
      switch (dto.getField()){
          case 0:
              field = "name";
              break;
          case 1:
              field = "prompt";
              break;
          case 2:
              field = "a.name";
      }
        List<Picture> pictures = pictureMapper.selectList(new MPJLambdaWrapper<Picture>()
                .selectAll(Picture.class)
                .leftJoin(dto.getField() == 2, "user a on t.creatorId = a.id")
                .eq(StrUtil.isNotBlank(dto.getPictureTypeName()), Picture::getTypeName, dto.getPictureTypeName())
                .like(field, dto.getInput())
                .eq(Picture::getShared,1)
        );
      return R.success(pictures);


    }

    public R<List<Picture>> searchUserPicture(@RequestBody SearchUserPictureParamDto dto){

        String field =  "name";
        if(dto.getSearchField()>0){
            field  = "prompt";
        }


        List<Picture> pictures = pictureMapper.selectList(new MPJLambdaWrapper<Picture>()
                .selectAll(Picture.class)
                .leftJoin(Picturecollected.class, on -> on
                        .eq(Picturecollected::getUserId, dto.getUserId())
                        .eq(Picturecollected::getPictureId, Picture::getId)
                )
                .eq(StrUtil.isNotBlank(dto.getTypeName()),Picture::getTypeName,dto.getTypeName())
                .like(field,String.format("%%%s%%",dto.getInput()))
                .isNotNull(Picturecollected::getPictureId)

        );

        return  R.success(pictures);
    }

    public R<String> cancelShare(@RequestBody CancelShareParamDto dto){
        pictureMapper.update(null,new UpdateWrapper<Picture>().lambda()
                .eq(Picture::getId,dto.getPictureId())
                .set(Picture::getShared,0)
        );
        return  R.success(null);
    }

    public R<String> sharePicture( SharePictureParamDto dto){
        pictureMapper.update(null,new UpdateWrapper<Picture>().lambda()
                .eq(Picture::getId,dto.getPictureId())
                .set(Picture::getShared,1)
        );
        return  R.success(null);
    }


    public R<String> cancelCollect( CancelCollectParamDto dto){
       picturecollectedMapper.delete(new QueryWrapper<Picturecollected>().lambda()
               .eq(Picturecollected::getPictureId,dto.getPictureId())
               .eq(Picturecollected::getUserId,dto.getUserId())
       );
       return R.success(null);
    }

    public R<String> collectPicture( CollectPictureParamDto dto){

        picturecollectedMapper.insert(Picturecollected.builder()
                        .pictureId(dto.getPictureId())
                        .userId(dto.getUserId())
                .build());

        Type type = typeMapper.selectOne(new QueryWrapper<Type>().lambda()
                .eq(Type::getUserId, dto.getUserId())
                .eq(Type::getTypeName, dto.getTypeName())
        );
        if(type == null) {
            typeMapper.insert(Type.builder()
                    .typeName(dto.getTypeName())
                    .userId(dto.getUserId())
                    .build());
        }

          pictureMapper.update(null,new UpdateWrapper<Picture>().lambda()
                  .eq(Picture::getId,dto.getPictureId())
                          .set(Picture::getName,dto.getName())
                  .set(Picture::getTypeName,dto.getTypeName()));


        return R.success(null);

    }

    public R<String> uploadImage(@RequestBody UploadImageParamDto dto) throws IOException {
        String fileName = dto.getFile().getOriginalFilename();
        String post = fileName.substring(fileName.lastIndexOf('.'));
        fileName  = fileName.substring(0,fileName.lastIndexOf('.'));
        fileName = fileName+System.currentTimeMillis()+post;
        dto.getFile().transferTo(new File(imagePath+fileName));
        return  R.success("/image/"+fileName);
    }
    public R<List<Picture>> searchPictures( SearchPicturesParamDto dto){

        List<Picture> pictures;
        switch (dto.getField()){
            case "authorName":
                pictures = pictureMapper.getPictureByAuthorName(String.format("%%%s%%",dto.getInput()));
break;
            case "name":
                pictures = pictureMapper.selectList(new QueryWrapper<Picture>().lambda()
                        .eq(dto.getUserId()!= 0,Picture::getCreatorId,dto.getUserId())
                        .like(Picture::getName,String.format("%%%s%%",dto.getInput()))
                        .eq(dto.getUserId()==0,Picture::getShared,1));
                break;

            default:
            pictures = pictureMapper.selectList(new QueryWrapper<Picture>().lambda()
                    .eq(dto.getUserId()!= 0,Picture::getCreatorId,dto.getUserId())
                    .like(Picture::getPrompt,String.format("%%%s%%",dto.getInput()))
                    .eq(dto.getUserId()==0,Picture::getShared,1)
            );

        }
        if(StrUtil.isNotBlank(dto.getTypeName())){
            pictures = pictures.stream().filter(picture -> picture.getTypeName().equals(dto.getTypeName()))
                    .collect(Collectors.toList());
        }
        return  R.success(pictures);

    }
    public R<List<String>> getAllPictureTypes(){
        List<String> typeList = typeMapper.selectObjs(new QueryWrapper<Type>().lambda()
                .select(Type::getTypeName)
                .groupBy(Type::getTypeName)).stream().map(Object::toString).collect(Collectors.toList());
        return  R.success(typeList);
    }

    public R<List<Type>> getUserPictureTypes( GetPictureTypesParamDto dto){
        List<Type> types = typeMapper.selectList(new QueryWrapper<Type>().lambda().


                eq(Type::getUserId, dto.getUserId())
        );

        return  R.success(types);
    }

    public R<Picture> generatePictureWithText( GeneratePictureWithTextParamDto dto){
        int scale = 12;
        int steps = dto.getStep();
        int seed = 1850517482;
        JSONObject body = new JSONObject();
        body.put("prompt",dto.getPrompt().replace("\n",""));
        body.put("width",dto.getWidth());
        body.put("height",dto.getHeight());
        body.put("scale",scale);
        body.put("sampler","k_euler_ancestral");
        body.put("steps",steps);
        body.put("seed",seed);
        body.put("n_samples",1);
        body.put("ucPreset",0);
        body.put("strength",dto.getStrength());
        body.put("noise",dto.getNoise());
        body.put("uc","lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry");

//        调用调用部署在本地的novel的接口
        String res = HttpRequest.post("http://localhost:6969/generate-stream").body(body.toJSONString()).execute().body();

//        获取生成的图片地址
        Matcher matcher = Pattern.compile("(src: )(.*)").matcher(res);
        matcher.find();
        String imageName = matcher.group(2);
        String imgSrc = address+imageName;

        Picture picture = Picture.builder()
                .prompt(dto.getPrompt())
                .scale(scale)
                .noise(dto.getNoise())
                .creatorId(dto.getUserId())
                .url(imgSrc)
                .step(steps)
                .strength(dto.getStrength())
                .build();

        pictureMapper.insert(picture);
        return R.success(picture);

    }


}
